package view;

import graphics.Painter;
import interfaces.Observer;

import java.util.ArrayList;
import java.util.List;

import logic.CollisionHandler;
import logic.GameLogicHandler;
import models.GeneralObject;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;

/**
 *
 * @author Merete, Mirna, Esben, Knut og Stian
 *
 */
public class MainThread extends Thread {

		private static final String TAG = MainThread.class.getSimpleName();
		private static MainThread mt;
		private boolean running;
		private SurfaceHolder surfaceHolder;
		private final static int MAX_FPS = 60;
		private final static int MAX_FRAME_SKIPS = 5;
		private final static int FRAME_PERIOD = 1000 / MAX_FPS;
		private Painter painter;
		private GameLogicHandler glh;
		private long tickCount;

		public void setRunning(boolean running) {
			this.running = running;
		}

		public long getTickCount() {
			return tickCount;
		}

		private MainThread(SurfaceHolder surfaceHolder, MainView gamePanel) {
			super();
			this.surfaceHolder = surfaceHolder;
		}

		public static synchronized MainThread getInstance(SurfaceHolder surfaceHolder, MainView gamePanel) {
			if(mt == null) {
				return mt = new MainThread(surfaceHolder, gamePanel);
			} else {
				return mt;
			}
		}

		/*
		 * Sender videre objektlisten til painter og glh
		 */
		public void initPainterAndGLH(ArrayList <GeneralObject> list){
			glh = new GameLogicHandler(list);
			painter = new Painter(list);



			Log.d(TAG, "glh added to observer list" );
		}

		@Override
		public void run() {
			tickCount = 0;
			Canvas canvas;
			Log.d(TAG, "starting game loop");

			long beginTime;
			long timeDiff;
			int sleepTime;
			int framesSkipped;

			sleepTime = 0;

			while(running) {
				canvas = null;
				tickCount++;
				try {
					canvas = this.surfaceHolder.lockCanvas();
					synchronized (surfaceHolder) {
						beginTime = System.currentTimeMillis();
						framesSkipped = 0;
						//update game state
						this.glh.update();
						//render state to the screen
						this.painter.draw(canvas);
						//calculate the cycle length
						timeDiff = System.currentTimeMillis() - beginTime;
						sleepTime = (int)(FRAME_PERIOD - timeDiff);

						if(sleepTime > 0){
							try {
								Thread.sleep(sleepTime);
							} catch (InterruptedException e) {

							}
						}

						while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
							//we need to play catch up
							this.glh.update();
							sleepTime += FRAME_PERIOD;
							framesSkipped++;
						}
					}
				}
				finally {
					//in case of exception
					if (canvas != null) {
						surfaceHolder.unlockCanvasAndPost(canvas);
					}
				}


			}
			Log.d(TAG, "Game loop executed " + tickCount + " times");
		}



}
